package com.db_tenant;


import com.db_tenant.citus.CoordinateTenant;
import com.db_tenant.citus.WorkerTenant;
import io.ebean.EbeanServer;
import io.ebean.EbeanServerFactory;
import io.ebean.config.ServerConfig;
import io.ebean.config.TenantMode;
import io.ebean.config.dbplatform.postgres.PostgresPlatform;
import org.jooq.lambda.Seq;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

import javax.sql.DataSource;
import java.util.List;

@Configuration
public abstract class CitusRwTenantConfig {

  public CitusRwTenantConfig(){
    System.out.println("创建 CitusRwTenantConfig");
  }

  EbeanServer ebeanServer(ThreadLocalTenant tlTenant, CitusDataSrcProvider provider) {
    ServerConfig config = new ServerConfig();

    config.setDatabasePlatform(new PostgresPlatform());
    config.setTenantMode(TenantMode.DB);
    config.setCurrentTenantProvider(tlTenant);
    config.setTenantDataSourceProvider(provider);

    return EbeanServerFactory.create(config);
  }

  //----------------
  @Bean
  @Lazy
  public CoordinateTenant coordTennant() {
    //dbc:postgresql://<host>:<port>/<database_name>
    String jdbcUrl = String.format("jdbc:postgresql://%s:%s/%s", coordinate(), port(), database());
    return new CoordinateTenant(jdbcUrl, username(), password());
  }

  @Bean(name = "workderTennants")
  @Lazy
  public List<WorkerTenant> workderTennants() {
    return Seq.seq(workers())
            .map(workerIp -> String.format("jdbc:postgresql://%s:%s/%s", workerIp, port(), database()))
            .map(url -> new WorkerTenant(url, username(), password()))
            .toList();
  }

  @Bean(name = "allNodeDataSources")
  @Lazy
  public List<DataSource> allNodeDataSources() {
    return Seq.seq(workderTennants())
            .map(t -> t.dataSource())
            .append(coordTennant().dataSource())
            .toList();
  }

  //----------------
  public abstract String coordinate();

  public abstract List<String> workers();

  public abstract String port();

  public abstract String database();

  public abstract String username();

  public abstract String password();

}
